package za.ac.wits.was.user.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import za.ac.wits.was.courses.allocations.CourseAllocations;
import za.ac.wits.was.disciplines.Discipline;
import za.ac.wits.was.research.ResearchAllocations;
import za.ac.wits.was.user.model.AcademicStaff;
import za.ac.wits.was.user.model.Authority;
import za.ac.wits.was.user.model.Coordinator;
import za.ac.wits.was.user.model.HOD;
import za.ac.wits.was.user.model.User;

/**
 *
 * @author Salman Noor : School of Electrical and Information Engineering
 * @Copyright: Wits University 2013 - All Rights Reserved
 * @email: salmannoor74415@gmail.com
 * @License: BSD License (http://www.linfo.org/bsdlicense.html)
 */
@Service
public class UserService {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public String getUserFullName(String username) {
        Session sess = this.sessionFactory.openSession();
        User systemUser = (User) sess.createQuery("from was_user where username = :username").setParameter("username", username).uniqueResult();
        sess.flush();
        sess.close();
        if (systemUser == null) {
            return "";
        } else {
            return systemUser.getFirstname() + " " + systemUser.getLastname();
        }
    }

    public List<ResearchAllocations> getAllResearch(String username) {
        Session sess = this.sessionFactory.openSession();
        AcademicStaff systemUser = (AcademicStaff) sess.createQuery("from was_user where username = :username").setParameter("username", username).uniqueResult();
        Set<ResearchAllocations> ra = systemUser.getResearch_allocations();
        for (ResearchAllocations r : ra){
                r.getAcademic_staff_member();
        }
        sess.flush();
        sess.close();

        List<ResearchAllocations> resAll = new ArrayList();
        if (ra == null) {
            return resAll;
        }
        resAll.addAll(ra);
        return resAll;
    }

    public List<CourseAllocations> getAllCourses(String username) {
        Session sess = this.sessionFactory.openSession();
        AcademicStaff systemUser = (AcademicStaff) sess.createQuery("from was_user where username = :username").setParameter("username", username).uniqueResult();
        Set<CourseAllocations> ca = systemUser.getCourse_allocations();
        for (CourseAllocations c : ca) {
            c.getAcademic_staff_member();
            c.getCourse();
        }
        sess.flush();
        sess.close();

        List<CourseAllocations> courseAll = new ArrayList();
        if (ca == null) {
            return courseAll;
        }
        courseAll.addAll(ca);
        return courseAll;
    }

    public User authenticateUser(String username, String password) {
        Session sess = this.sessionFactory.openSession();
        User systemUser = (User) sess.createQuery("from was_user where username = :username and password = :password").setParameter("username", username).setParameter("password", password).uniqueResult();
        if (systemUser == null) {
            return null;
        } else if (systemUser.getUser_def().equalsIgnoreCase("coordinator")) {
            return (Coordinator) systemUser;
        } else if (systemUser.getUser_def().equalsIgnoreCase("hod")) {
            return (HOD) systemUser;
        } else if (systemUser.getUser_def().equalsIgnoreCase("academic_staff")) {
            return (AcademicStaff) systemUser;
        }
        sess.flush();
        sess.close();
        return null;
    }

    public List<AcademicStaff> getAllAcademicStaff() {
        Session sess = this.sessionFactory.openSession();
        List<AcademicStaff> theList = sess.createQuery("from AcademicStaff").list();
        sess.flush();
        sess.close();
        return theList;
    }

    public AcademicStaff updateAcademicStaff(AcademicStaff updatedAcademicStaff) {
        Session sess = this.sessionFactory.openSession();
        AcademicStaff ac = (AcademicStaff) sess.get(AcademicStaff.class, updatedAcademicStaff.getUser_id());
        Discipline dc = (Discipline) sess.get(Discipline.class, updatedAcademicStaff.getDiscipline_id());
        ac.setDiscipline(dc);
        ac.setUsername(updatedAcademicStaff.getUsername());
        ac.setPassword(updatedAcademicStaff.getPassword());
        ac.setFirstname(updatedAcademicStaff.getFirstname());
        ac.setLastname(updatedAcademicStaff.getLastname());
        ac.setEmail_address(updatedAcademicStaff.getEmail_address());
        ac.setCitizenship_percentage(updatedAcademicStaff.getCitizenship_percentage());
        ac.setContract_type(updatedAcademicStaff.getContract_type());
        ac.setJob_position(updatedAcademicStaff.getJob_position());
        ac.setQualification(updatedAcademicStaff.getQualification());
        ac.setResearch_percentage(updatedAcademicStaff.getResearch_percentage());
        ac.setStaff_number(updatedAcademicStaff.getStaff_number());
        ac.setTeaching_percentage(updatedAcademicStaff.getTeaching_percentage());
        ac.setTotal_hours(updatedAcademicStaff.getTotal_hours());



        sess.saveOrUpdate(ac);
        sess.flush();
        sess.close();
        return ac;
    }

    public AcademicStaff createNewAcademicStaff(AcademicStaff newAcademicStaff) {
        Session sess = this.sessionFactory.openSession();
        Discipline dc = (Discipline) sess.get(Discipline.class, newAcademicStaff.getDiscipline_id());
        newAcademicStaff.setDiscipline(dc);
        newAcademicStaff.setAcademic_user(Boolean.TRUE);
        newAcademicStaff.setUser_def("academic_staff");
        HashSet<Authority> newAcademicStaffAuthorities = new HashSet();
        newAcademicStaffAuthorities.add((Authority) sess.createQuery("from was_authority where authority= :authority").setParameter("authority", "ROLE_STAFF").uniqueResult());
        newAcademicStaff.setUser_authorities(newAcademicStaffAuthorities);
        sess.save(newAcademicStaff);
        sess.flush();
        sess.close();
        return newAcademicStaff;
    }

    public AcademicStaff deleteAcademicStaff(AcademicStaff existingAcademicStaff) {
        Session sess = this.sessionFactory.openSession();
        AcademicStaff usertobeDeleted = (AcademicStaff) sess.get(AcademicStaff.class, existingAcademicStaff.getUser_id());
        usertobeDeleted.getUser_authorities().clear();
        sess.saveOrUpdate(usertobeDeleted);
        for (CourseAllocations ax : usertobeDeleted.getCourse_allocations()) {
            sess.delete(ax);
        }
        for (ResearchAllocations rx : usertobeDeleted.getResearch_allocations()) {
            sess.delete(rx);
        }
        sess.delete(usertobeDeleted);
        sess.flush();
        sess.close();
        return existingAcademicStaff;
    }

    public Boolean userExists(String username) {
        Session sess = this.sessionFactory.openSession();
        User systemUser = (User) sess.createQuery("from was_user where username = :username ").setParameter("username", username).uniqueResult();
        sess.flush();
        sess.close();
        if (systemUser == null) {
            return false;
        }
        return true;
    }
}
